package com.chuxing.security.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.chuxing.config.SecurityRole;
import com.chuxing.domain.User;
import com.chuxing.exception.GenericException;
import com.chuxing.exception.UnauthorizedException;
import com.chuxing.security.mapper.UserMapper;
import com.chuxing.security.service.ImageService;
import com.chuxing.utils.MinioUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.util.UUID;

/**
* @author HP
* @description 针对表【t_image】的数据库操作Service实现
* @createDate 2024-11-29 22:19:14
*/
@Service
@Transactional
@RequiredArgsConstructor
public class ImageServiceImpl implements ImageService{

    private final MinioUtil minioUtil;

    private final UserMapper userMapper;

    /**
     * 上传图片接口
     * 该方法主要用于用户上传图片，只接受图片类型的内容
     * 在上传图片之前，会检查文件类型是否为图片
     * 上传成功后，将删除之前缓存的用户信息，以确保数据一致性
     *
     * @param file 用户上传的图片文件，必须是图片类型
     * @return 返回上传图片的URL地址
     */
    @CacheEvict(value = "userInfo", allEntries=true)
    @Override
    public String uploadImage(@RequestBody MultipartFile file) {
        //判断文件类型是不是图片
        String contentType = file.getContentType();
        if (contentType != null && !contentType.startsWith("image")) {
            throw new GenericException("文件类型不是图片");
        }
        //生成唯一文件名，防止文件重名
        UUID uuid = UUID.randomUUID();
        //取出文件的后缀
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        //拼接文件名和后缀
        String url = uuid +suffix;
        //调用MinIO工具类上传文件
        minioUtil.uploadObject(file, url);
        //根据登录用户的学号查询用户信息
        User user = userMapper.selectByStudentId(StpUtil.getLoginIdAsString());
        //删除用户之前的头像文件
        minioUtil.removeObject(user.getStuImage());
        //更新用户信息中的头像URL
        userMapper.updateStuImageByStudentId(url, user.getStudentId());
        //返回上传图片的URL地址
        return url;
    }


    /**
     * 根据URL获取图像的InputStream
     * 该方法使用MinIO对象存储服务来检索图像数据
     *
     * @param URL 图像的唯一标识符，用于在对象存储中定位图像
     * @return InputStream 图像的数据流，可以用于进一步处理或显示图像
     */
    @Override
    public void getImage(String URL, HttpServletResponse response) {
        minioUtil.downloadObject(response, URL);
    }

    /**
     * 根据管理员身份删除指定学生的图像信息
     * 此方法首先验证当前操作者是否已登录，并且具有管理员角色，以确保操作的安全性和合法性
     * 如果未登录或权限不足，将抛出相应的异常如果权限验证通过，将根据提供的学生ID删除图像信息
     *
     * @param studentId 学生ID，用于标识需要删除图像信息的学生
     * @throws UnauthorizedException 如果当前用户未登录，抛出此异常
     * @throws GenericException 如果当前用户不是管理员，抛出此异常
     */
    @Override
    public void deleteImageByAdmin(String studentId) {
        // 检查当前用户是否已登录
        if(!StpUtil.isLogin()){
            throw new UnauthorizedException("未登录");
        }
        // 检查当前用户是否具有管理员角色
        if(!StpUtil.hasRole(SecurityRole.ROLE_ADMIN)){
            throw new GenericException("权限不足");
        }
        // 删除指定学生ID的图像信息
        User user = userMapper.selectByStudentId(studentId);
        // 如果用户存在且其图像信息不为空，则删除图像信息
        if(user!=null && user.getStuImage()!=null){
            minioUtil.removeObject(user.getStuImage());
        }
    }
}




